package com.wenx.v3system.modular.platform.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wenx.v3core.error.BusinessException;
import com.wenx.v3dynamicdatasourcestarter.config.DynamicDataSourceConfig;
import com.wenx.v3secure.enums.PlatformRoleType;
import com.wenx.v3system.modular.platform.domain.dto.PlatformUserDto;
import com.wenx.v3system.modular.platform.domain.maps.PlatformUserMap;
import com.wenx.v3system.modular.platform.domain.po.PlatformUser;
import com.wenx.v3system.modular.platform.domain.query.PlatformUserQuery;
import com.wenx.v3system.modular.platform.mapper.PlatformUserMapper;
import com.wenx.v3system.modular.platform.service.PlatformRoleMenuService;
import com.wenx.v3system.modular.platform.service.PlatformUserRoleService;
import com.wenx.v3system.modular.platform.service.PlatformUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 平台用户服务实现类
 * 基于简化权限模型重构
 * 使用v3-platform数据源
 * 
 * @author wenx
 */
@Service
@DS(DynamicDataSourceConfig.PLATFORM_DATASOURCE)
public class PlatformUserServiceImpl extends ServiceImpl<PlatformUserMapper, PlatformUser> implements PlatformUserService {

    private static final Logger log = LoggerFactory.getLogger(PlatformUserServiceImpl.class);
    
    private final PasswordEncoder passwordEncoder;
    private final PlatformRoleMenuService roleMenuService;
    private final PlatformUserRoleService userRoleService;
    
    public PlatformUserServiceImpl(PasswordEncoder passwordEncoder, 
                                   PlatformRoleMenuService roleMenuService, 
                                   PlatformUserRoleService userRoleService) {
        this.passwordEncoder = passwordEncoder;
        this.roleMenuService = roleMenuService;
        this.userRoleService = userRoleService;
    }

    @Override
    public IPage<?> page(PlatformUserQuery query) {
        log.debug("分页查询平台用户，查询条件: {}", query);
        
        LambdaQueryWrapper<PlatformUser> wrapper = new LambdaQueryWrapper<PlatformUser>()
                .like(StringUtils.hasText(query.getUsername()), PlatformUser::getUsername, query.getUsername())
                .like(StringUtils.hasText(query.getRealName()), PlatformUser::getRealName, query.getRealName())
                .like(StringUtils.hasText(query.getEmail()), PlatformUser::getEmail, query.getEmail())
                .eq(query.getStatus() != null, PlatformUser::getStatus, query.getStatus())
                .orderByDesc(PlatformUser::getCreateTime);
        
        IPage<PlatformUser> result = super.page(new Page<>(query.getCurrent(), query.getSize()), wrapper);
        return result.convert(this::convertToDto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(PlatformUserDto dto) {
        log.info("创建平台用户，数据: {}", dto);
        
        // 参数校验
        if (!StringUtils.hasText(dto.getUsername())) {
            throw new BusinessException("用户名不能为空");
        }
        if (!StringUtils.hasText(dto.getRealName())) {
            throw new BusinessException("真实姓名不能为空");
        }
        
        // 唯一性校验
        if (checkUsernameExists(dto.getUsername(), null)) {
            throw new BusinessException("用户名已存在");
        }
        
        if (StringUtils.hasText(dto.getEmail()) && checkEmailExists(dto.getEmail(), null)) {
            throw new BusinessException("邮箱已存在");
        }

        PlatformUser user = PlatformUserMap.INSTANCE.toPo(dto);
        
        // 设置默认值
        user.setUserType("platform");
        user.setStatus(dto.getStatus() != null ? dto.getStatus() : 1);
        user.setLoginCount(0);
        user.setMustChangePassword(false);
        user.setTwoFactorEnabled(false);
        // 时间字段由MyBatis-Plus自动填充
        
        // 密码处理
        if (StringUtils.hasText(dto.getPassword())) {
            user.setPassword(passwordEncoder.encode(dto.getPassword()));
        } else {
            // 生成随机密码
            String randomPassword = generateRandomPassword();
            user.setPassword(passwordEncoder.encode(randomPassword));
            user.setMustChangePassword(true);
            log.info("为用户 {} 生成随机密码", dto.getUsername());
        }
        
        super.save(user);
        
        // 分配角色 - 优先使用roleIds，兼容roleCodes
        List<String> rolesToAssign = null;
        if (!CollectionUtils.isEmpty(dto.getRoleIds())) {
            rolesToAssign = dto.getRoleIds();
        } else if (!CollectionUtils.isEmpty(dto.getRoleCodes())) {
            rolesToAssign = dto.getRoleCodes();
        }
        
        if (!CollectionUtils.isEmpty(rolesToAssign)) {
            assignUserRoles(user.getId(), rolesToAssign);
        } else {
            // 分配默认角色
            assignUserRoles(user.getId(), Arrays.asList(PlatformRoleType.PLATFORM_SUPPORT.getCode()));
        }
        
        log.info("平台用户创建成功: userId={}, username={}", user.getId(), user.getUsername());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Serializable id) {
        log.info("删除平台用户，用户ID: {}", id);
        
        PlatformUser user = super.getById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 检查是否为超级管理员
        if (isSuperAdmin(user.getId())) {
            throw new BusinessException("不能删除超级管理员");
        }
        
        // 检查用户状态
        if (user.getStatus() == 1) {
            log.warn("尝试删除活跃用户: userId={}, username={}", id, user.getUsername());
        }
        
        // 删除用户角色关联
        userRoleService.removeUserRoles((Long) id);
        
        // 删除用户
        super.removeById(id);
        
        // 清除缓存
        clearUserPermissionCache(user.getId());
        
        log.info("平台用户删除成功: userId={}, username={}", id, user.getUsername());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(PlatformUserDto dto) {
        log.info("更新平台用户，数据: {}", dto);
        
        if (dto.getId() == null) {
            throw new BusinessException("用户ID不能为空");
        }
        
        PlatformUser existingUser = super.getById(dto.getId());
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 检查是否为超级管理员的关键信息修改
        if (isSuperAdmin(dto.getId())) {
            if (!Objects.equals(existingUser.getUsername(), dto.getUsername())) {
                throw new BusinessException("不能修改超级管理员用户名");
            }
            if (dto.getStatus() != null && dto.getStatus() != 1) {
                throw new BusinessException("不能禁用超级管理员");
            }
        }
        
        // 检查用户名唯一性（排除自己）
        if (!Objects.equals(existingUser.getUsername(), dto.getUsername()) && 
            checkUsernameExists(dto.getUsername(), dto.getId())) {
            throw new BusinessException("用户名已存在");
        }
        
        // 检查邮箱唯一性（排除自己）
        if (StringUtils.hasText(dto.getEmail()) && 
            !Objects.equals(existingUser.getEmail(), dto.getEmail()) &&
            checkEmailExists(dto.getEmail(), dto.getId())) {
            throw new BusinessException("邮箱已存在");
        }

        PlatformUser user = PlatformUserMap.INSTANCE.toPo(dto);
        
        // 密码处理
        if (StringUtils.hasText(dto.getPassword())) {
            user.setPassword(passwordEncoder.encode(dto.getPassword()));
            user.setMustChangePassword(false);
        } else {
            // 保持原密码和相关设置
            user.setPassword(existingUser.getPassword());
            user.setMustChangePassword(existingUser.getMustChangePassword());
            user.setPasswordExpireTime(existingUser.getPasswordExpireTime());
        }
        
        // 保持一些不应该被修改的字段
        user.setUserType(existingUser.getUserType());
        user.setLoginCount(existingUser.getLoginCount());
        user.setLastLoginTime(existingUser.getLastLoginTime());
        user.setLastLoginIp(existingUser.getLastLoginIp());
        
        // 重要：设置version字段以支持乐观锁
        user.setVersion(existingUser.getVersion());
        
        super.updateById(user);
        
        // 更新角色关联 - 优先使用roleIds，兼容roleCodes
        List<String> rolesToAssign = null;
        if (!CollectionUtils.isEmpty(dto.getRoleIds())) {
            rolesToAssign = dto.getRoleIds();
        } 
        
        if (!CollectionUtils.isEmpty(rolesToAssign)) {
            // 重新分配角色（assignUserRoles内部会先删除原有角色）
            assignUserRoles(dto.getId(), rolesToAssign);
        }
        
        // 清除缓存
        clearUserPermissionCache(dto.getId());
        
        log.info("平台用户更新成功: userId={}, username={}", dto.getId(), dto.getUsername());
    }

    @Override
    public Object get(Serializable id) {
        PlatformUser user = super.getById(id);
        return user != null ? convertToDto(user) : null;
    }

    @Override
    public PlatformUserDto getUserByUsername(String username) {
        PlatformUser user = this.getOne(
            new LambdaQueryWrapper<PlatformUser>()
                .eq(PlatformUser::getUsername, username)
                .eq(PlatformUser::getDeleted, 0)
        );
        return user != null ? convertToDto(user) : null;
    }

    @Override
    public PlatformUserDto login(String username, String password) {
        PlatformUser user = this.getOne(
            new LambdaQueryWrapper<PlatformUser>()
                .eq(PlatformUser::getUsername, username)
                .eq(PlatformUser::getStatus, 1)
                .eq(PlatformUser::getDeleted, 0)
        );
        
        if (user == null || !passwordEncoder.matches(password, user.getPassword())) {
            return null;
        }
        
        // 更新登录信息
        updateLastLoginInfo(user.getId(), null);
        
        return convertToDto(user);
    }

    @Override
    @Cacheable(value = "platform:user:roles", key = "#userId")
    public List<String> getUserRoles(Long userId) {
        return userRoleService.getRoleCodesByUserId(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignUserRoles(Long userId, List<String> roleIds) {
        userRoleService.assignUserRoles(userId, roleIds);
        log.info("用户角色分配成功: userId={}, roleIds={}", userId, roleIds);
    }

    @Override
    @Cacheable(value = "platform:user:permissions", key = "#userId")
    public List<String> getUserPermissions(Long userId) {
        List<String> userRoles = getUserRoles(userId);
        Set<String> permissions = new HashSet<>();
        
        for (String roleCode : userRoles) {
            PlatformRoleType roleType = PlatformRoleType.fromCode(roleCode);
            if (roleType != null) {
                permissions.addAll(roleType.getPermissions());
            }
        }
        
        return new ArrayList<>(permissions);
    }

    @Override
    public boolean hasPermission(Long userId, String permission) {
        List<String> userPermissions = getUserPermissions(userId);
        return userPermissions.stream()
            .anyMatch(p -> com.wenx.v3secure.enums.PlatformPermission.hasPermission(p, permission));
    }

    @Override
    public List<String> getUserAccessibleTenants(Long userId) {
        // 简化实现：超级管理员可访问所有租户，其他用户暂时返回空列表
        if (isSuperAdmin(userId)) {
            return List.of(); // 空列表表示可访问所有租户
        }
        // 简化权限模型：暂时返回空列表，后续可根据需要扩展
        return List.of();
    }

    @Override
    public void setUserTenantAccess(Long userId, String accessType, List<String> tenantIds) {
        // 简化权限模型：暂时不做实际存储，仅记录日志
        log.info("设置用户租户访问权限: userId={}, accessType={}, tenantIds={}", userId, accessType, tenantIds);
    }

    @Override
    public boolean canAccessTenant(Long userId, String tenantId) {
        if (isSuperAdmin(userId)) {
            return true;
        }
        
        List<String> accessibleTenants = getUserAccessibleTenants(userId);
        return accessibleTenants.isEmpty() || accessibleTenants.contains(tenantId);
    }

    @Override
    public String resetUserPassword(Long userId) {
        PlatformUser user = super.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        String newPassword = generateRandomPassword();
        user.setPassword(passwordEncoder.encode(newPassword));
        user.setMustChangePassword(true);
        user.setPasswordExpireTime(Date.from(LocalDateTime.now().plusDays(7).atZone(ZoneId.systemDefault()).toInstant()));
        
        super.updateById(user);
        log.info("用户密码重置成功: userId={}", userId);
        return newPassword;
    }

    @Override
    public void updateUserStatus(Long userId, Integer status) {
        PlatformUser user = super.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        user.setStatus(status);
        super.updateById(user);
        log.info("用户状态更新成功: userId={}, status={}", userId, status);
    }

    @Override
    public void updateLastLoginInfo(Long userId, String loginIp) {
        PlatformUser user = new PlatformUser();
        user.setId(userId);
        user.setLastLoginTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        if (StringUtils.hasText(loginIp)) {
            user.setLastLoginIp(loginIp);
        }
        
        PlatformUser existingUser = super.getById(userId);
        if (existingUser != null) {
            user.setLoginCount(existingUser.getLoginCount() + 1);
        }
        
        super.updateById(user);
    }

    @Override
    public boolean checkUsernameExists(String username, Long excludeId) {
        LambdaQueryWrapper<PlatformUser> wrapper = new LambdaQueryWrapper<PlatformUser>()
            .eq(PlatformUser::getUsername, username)
            .eq(PlatformUser::getDeleted, 0);
        
        if (excludeId != null) {
            wrapper.ne(PlatformUser::getId, excludeId);
        }
        
        return this.count(wrapper) > 0;
    }

    @Override
    public boolean checkEmailExists(String email, Long excludeId) {
        if (!StringUtils.hasText(email)) {
            return false;
        }
        
        LambdaQueryWrapper<PlatformUser> wrapper = new LambdaQueryWrapper<PlatformUser>()
            .eq(PlatformUser::getEmail, email)
            .eq(PlatformUser::getDeleted, 0);
        
        if (excludeId != null) {
            wrapper.ne(PlatformUser::getId, excludeId);
        }
        
        return this.count(wrapper) > 0;
    }

    @Override
    public List<String> getUserMenuCodes(Long userId) {
        List<String> userRoles = getUserRoles(userId);
        return roleMenuService.getUserMenuCodes(userRoles);
    }

    @Override
    public boolean isSuperAdmin(Long userId) {
        List<String> userRoles = getUserRoles(userId);
        return userRoles.contains(PlatformRoleType.SUPER_ADMIN.getCode());
    }

    /**
     * 转换为DTO
     */
    private PlatformUserDto convertToDto(PlatformUser user) {
        PlatformUserDto dto = PlatformUserMap.INSTANCE.toDto(user);
        
        // 设置角色和权限信息
        dto.setRoleCodes(getUserRoles(user.getId()));
        dto.setPermissions(getUserPermissions(user.getId()));
        dto.setMenuCodes(getUserMenuCodes(user.getId()));
        dto.setAccessibleTenants(getUserAccessibleTenants(user.getId()));
        dto.setIsSuperAdmin(isSuperAdmin(user.getId()));
        
        return dto;
    }

    /**
     * 生成随机密码
     */
    private String generateRandomPassword() {
        return UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }

    @Override
    @CacheEvict(value = {"platform:user:roles", "platform:user:permissions"}, key = "#userId")
    public void clearUserPermissionCache(Long userId) {
        log.info("清除平台用户权限缓存: userId={}", userId);
    }

    @Override
    @CacheEvict(value = {"platform:user:roles", "platform:user:permissions"}, allEntries = true)
    public void clearAllPermissionCache() {
        log.info("清除所有平台用户权限缓存");
    }
}